/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.functors;

import org.jetbrains.annotations.NotNull;

import static java.lang.Boolean.TRUE;

public enum Boolean
{
	True
	{
		public void ifTrue(final @NotNull NullaryFunctor trueFunctor)
		{
			trueFunctor.closure();
		}

		public void ifFalse(final @NotNull NullaryFunctor falseFunctor)
		{
		}

		public void choice(final @NotNull NullaryFunctor trueFunctor, final @NotNull NullaryFunctor falseFunctor)
		{
			trueFunctor.closure();
		}

		@NotNull
		public <R> R choiceReturn(final @NotNull NullaryReturningFunctor<R> trueFunctor, final @NotNull NullaryReturningFunctor<R> falseFunctor)
		{
			return trueFunctor.closure();
		}

		public boolean isTrue()
		{
			return true;
		}

		public boolean isFalse()
		{
			return false;
		}
	},
	False
	{
		public void ifTrue(final @NotNull NullaryFunctor trueFunctor)
		{
		}

		public void ifFalse(final @NotNull NullaryFunctor falseFunctor)
		{
			falseFunctor.closure();
		}

		public void choice(final @NotNull NullaryFunctor trueFunctor, final @NotNull NullaryFunctor falseFunctor)
		{
			falseFunctor.closure();
		}

		@NotNull
		public <R> R choiceReturn(final @NotNull NullaryReturningFunctor<R> trueFunctor, final @NotNull NullaryReturningFunctor<R> falseFunctor)
		{
			return falseFunctor.closure();
		}

		public boolean isTrue()
		{
			return false;
		}

		public boolean isFalse()
		{
			return true;
		}
	},
	;

	public abstract void ifTrue(final @NotNull NullaryFunctor trueFunctor);

	public abstract void ifFalse(final @NotNull NullaryFunctor falseFunctor);

	public abstract void choice(final @NotNull NullaryFunctor trueFunctor, final @NotNull NullaryFunctor falseFunctor);

	public abstract boolean isTrue();

	public abstract boolean isFalse();

	@NotNull
	public abstract <R> R choiceReturn(final @NotNull NullaryReturningFunctor<R> trueFunctor, final @NotNull NullaryReturningFunctor<R> falseFunctor);

	@NotNull
	public Boolean not()
	{
		return isTrue() ? False : True;
	}

	@NotNull
	public Boolean and(final @NotNull Boolean that)
	{
		return (this.isTrue() && that.isTrue()) ? True : False;
	}

	@NotNull
	public Boolean or(final @NotNull Boolean that)
	{
		if (this.isFalse() && that.isFalse())
		{
			return False;
		}
		return True;
	}

	@NotNull
	public Boolean xor(final @NotNull Boolean that)
	{
		if (this.equals(that))
		{
			return False;
		}
		return True;
	}

	@NotNull
	public Boolean nand(final @NotNull Boolean that)
	{
		if (this.isTrue() && that.isTrue())
		{
			return False;
		}
		return True;
	}

	@NotNull
	public Boolean nor(final @NotNull Boolean that)
	{
		if (this.isFalse() && that.isFalse())
		{
			return True;
		}
		return False;
	}

	@NotNull
	public Boolean eq(final @NotNull Boolean that)
	{
		if (this.equals(that))
		{
			return True;
		}
		return False;
	}

	@NotNull
	public static Boolean fromLegacyBoolean(final boolean value)
	{
		return value ? True : False;
	}

	@NotNull
	public static Boolean fromLegacy(final @NotNull java.lang.Boolean value)
	{
		return value.equals(TRUE) ? True : False;
	}

	public boolean toLegacyBoolean()
	{
		return this == True;
	}
}
